Algebraic Effects and Handlers
和訳すると代数的作用?
?
例外 といってしまうのがよくない気がする。まあわかるけど…
処理を他に任せる感じ
こういう Effect を使いますとだけ書いておいて、それをどう実行するかというのは別のところで書く
例: String を出力しますという Effect (Write : String -> ()) があったとして、Write を使っているコードのハンドラ (実行方法) を書く (標準出力に出力する。 (Write str) k -> print str; k () 。ここで k は継続) 、そのハンドラを使ってコードを実行すると、Write しているところで標準出力に出力される。
テストのときは他のハンドラを使うとかできる。
どこかの API を叩くとして、インタフェースだけ切っておいてテストのときはモックを使うとか
DB 操作、ロガー、エラーレポート、分散トレース、とかいろいろ Effect にして切り替えられそう
取ってきた継続を一度しか使えないようなものを oneshot と呼ぶ
合成可能
Effect を横に並べられる
厳密に Algebraic Effects なのかは不明
question.icon どのあたりが代数的なのか
パフォーマンスは?
現実的な例は?
いいところは?
他の DI のやり方と比べていいところは?
モジュールを切り替えるのとどっちがいいのか
モジュールのほうがコードがまとまっていていい気もする?わからんが
他のは環境から特定のインタフェースを満たしたモジュールを取ってきてそれを呼ぶみたいな感じになりそうなので、「環境から取ってくる」部分がなくなって嬉しいかもしれない
インタフェースのみでコードが書ける、走らせるときに実装を指定、という感じ?
実装を指定する場所が変わるだけ?
=> どうやら継続が使えるのがいいらしい?
モナドと違ってliftみたいな面倒なこともしなくていい。エフェクトを使いつつ地のレイヤーで操作できる
悪いところは?
Effect をたくさん使うと型が煩雑になりそう
同じ Effect でもいろいろな実装を使いたいとき難しそう
実際こういうことをしたいかどうかは不明
エラーが起きたときに無視したいかどうかとかだろうか
例えば DB アクセスのレイヤ (dao) を Effect にしたいとして、
find_user とか update_user とかをそれぞれ Effect にするのか
それぞれ実装を切り替えられるメリットは?
と思ったけど別にいい気がする
reader で環境から dao を取ってくる
Reader モナドでよくない?
Cake Pattern みたいなのでよくない?
現実的にはどうやって書けばいいのか
パターンみたいなのがまた生まれる?
ReadTransaction と WriteTransaction の Effect を作ってあとはそれらの wrapper を使う?うーん
ReadTransaction と WriteTransaction のところだけ実装を入れ替えられて嬉しいのかどうか
参考